<template>
  <div class="aprd-container">
    <!-- 搜索区域 -->
    <div class="aprd-search-container">
      <el-form :inline="true" :model="searchParams" class="aprd-search-form">
        <el-form-item label="开始时间">
          <el-date-picker v-model="searchParams.startTime" type="datetime" placeholder="选择日期时间"
            format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" size="small" />
        </el-form-item>
        <el-form-item label="结束时间">
          <el-date-picker v-model="searchParams.endTime" type="datetime" placeholder="选择日期时间"
            format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" size="small" />
        </el-form-item>
        <el-form-item label="出口卷号">
          <el-input v-model="searchParams.exitCoilNo" placeholder="请输入出口卷号" size="small" clearable></el-input>
        </el-form-item>
        <el-form-item label="宽度分档">
          <el-input v-model="searchParams.widthBin" placeholder="请输入" size="small" clearable> </el-input>
        </el-form-item>
        <el-form-item label="出口厚度分档">
          <el-input v-model="searchParams.exitThicknessBin" placeholder="请输入" size="small" clearable> </el-input>
        </el-form-item>
        <el-form-item label="钢种分档">
          <el-input v-model="searchParams.steelGradeBin" placeholder="请输入" size="small" clearable> </el-input>
        </el-form-item>
        <el-form-item label="是否跑偏">
          <el-select v-model="searchParams.paopianFlagTrue" placeholder="请选择" size="small" clearable style="width: 150px">
            <el-option label="全部" value="" />
            <el-option label="不跑偏" value="0" />
            <el-option label="跑偏" value="1" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch" size="small">查询</el-button>
          <el-button @click="handleReset" size="small">重置</el-button>
          <el-button type="success" @click="handleExport" size="small">导出</el-button>
        </el-form-item>
      </el-form>
    </div>

    <!-- 数据表格 -->
    <div class="aprd-table-container">
      <el-table :data="tableData" border style="width: 100%" :header-cell-style="headerStyle" height="100%">
        <el-table-column prop="seqNo" label="序号" width="60" fixed="left" align="center" />
        <el-table-column prop="extid" label="出口卷号" width="150" fixed="left" align="center">
          <template #default="scope">
            <span>{{ scope.row.extid !== undefined && scope.row.extid !== null && scope.row.extid !== '' ?
              scope.row.extid : '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="steelGrade" label="钢种" width="100" fixed="left" align="center">
          <template #default="scope">
            <span>{{ scope.row.steelGrade !== undefined && scope.row.steelGrade !== '' ? scope.row.steelGrade : '-'
              }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="width" label="宽度" width="100" fixed="left" align="center">
          <template #default="scope">
            <span>{{ scope.row.width !== undefined && scope.row.width !== '' ? scope.row.width : '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="thick" label="厚度" width="100" fixed="left" align="center">
          <template #default="scope">
            <span>{{ scope.row.thick !== undefined && scope.row.thick !== '' ? scope.row.thick : '-' }}</span>
          </template>
        </el-table-column>
        <!-- 带钢最大值放到厚度后边 -->
        <el-table-column label="带钢最大值" align="center">
          <el-table-column v-for="key in cpcStripMaxFields" :key="key" :prop="key" :label="getFieldLabel(key)"
            align="center">
            <template #default="scope">
              <span :style="{ color: Math.abs(scope.row[key]) > 30 ? 'red' : 'inherit' }">{{
                scope.row[key] !== undefined && scope.row[key] !== null && scope.row[key] !== '' ? scope.row[key] : '-'
              }}</span>
            </template>
          </el-table-column>
        </el-table-column>
        <!-- 动态基础字段 -->
        <el-table-column v-for="key in baseTableFields" :key="key" :prop="key" :label="getFieldLabel(key)"
          align="center"
          :width="key === 'entid' ? 150 : key === 'extid' ? 150 : key === 'prodEndTime' ? 180 : key === 'hotCoilId' ? 120 : undefined">
          <template #default="scope">
            <span v-if="isTimeField(key)">{{ formatDate(scope.row[key]) }}</span>
            <span v-else-if="key === 'paopianFlagTrue'">
              {{ scope.row[key] === 0 || scope.row[key] === '0' ? '不跑偏' : scope.row[key] === 1 || scope.row[key] === '1' ? '跑偏' : '-' }}
            </span>
            <span v-else>{{ scope.row[key] !== undefined && scope.row[key] !== '' ? scope.row[key] : '-' }}</span>
          </template>
        </el-table-column>
        <!-- 多级表头：CPC相关字段分组 -->
        <el-table-column label="纠偏缸均值" align="center">
          <el-table-column v-for="key in cpcAvgFields" :key="key" :prop="key" :label="getFieldLabel(key)"
            align="center">
            <template #default="scope">
              <span :style="{ color: Math.abs(scope.row[key]) > 80 ? 'red' : 'inherit' }">{{ scope.row[key] !==
                undefined && scope.row[key] !== null && scope.row[key] !== '' ? scope.row[key] : '-' }}</span>
            </template>
          </el-table-column>
        </el-table-column>
        <el-table-column label="带钢均值" align="center">
          <el-table-column v-for="key in cpcStripAvgFields" :key="key" :prop="key" :label="getFieldLabel(key)"
            align="center">
            <template #default="scope">
              <span :style="{ color: Math.abs(scope.row[key]) > 20 ? 'red' : 'inherit' }">{{
                scope.row[key] !== undefined && scope.row[key] !== null && scope.row[key] !== '' ? scope.row[key] : '-'
              }}</span>
            </template>
          </el-table-column>
        </el-table-column>
        <el-table-column prop="entid" label="入口卷号" width="150" align="center">
          <template #default="scope">
            <span>{{ scope.row.entid !== undefined && scope.row.entid !== null && scope.row.entid !== '' ?
              scope.row.entid : '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="prodEndTime" label="生产结束时间" width="180" align="center">
          <template #default="scope">
            <span>{{ formatDate(scope.row.prodEndTime) }}</span>
          </template>
        </el-table-column>
        <el-table-column label="详情" width="80" fixed="right" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="showDetail(scope.row)">详情</el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div class="aprd-pagination">
        <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize"
          :page-sizes="[5, 10, 15, 20, 25, 30]" background layout="total, sizes, prev, pager, next, jumper"
          :total="totalItems" @size-change="handleSizeChange" @current-change="handleCurrentChange" size="small" />
      </div>
    </div>

    <!-- 详情弹窗 -->
    <el-dialog v-model="detailDialogVisible" title="跑偏详细信息" width="90%" top="5vh" class="aprd-detail-dialog"
      destroy-on-close @closed="handleDialogClose" @opened="handleDialogOpened">
      <div class="aprd-detail-container">
        <!-- 顶部信息 -->
        <div class="aprd-detail-info">
          <el-descriptions :column="9" border size="small">
            <el-descriptions-item v-for="key in baseDetailFields" :key="key" :label="getFieldLabel(key)">
              <template #default>
                <span v-if="isTimeField(key)">{{ formatDate(detailData[key]) }}</span>
                <span v-else>{{ detailData[key] !== undefined && detailData[key] !== '' ? detailData[key] : '-'
                  }}</span>
              </template>
            </el-descriptions-item>
          </el-descriptions>
        </div>
        <!-- 图表区域 -->
        <div class="aprd-detail-charts-area">
          <!-- 左侧 CPC 图表区 -->
          <div class="aprd-left-charts">
            <div class="aprd-cpc-charts-list">
              <div v-for="(item, index) in detailData.cpcData" :key="item.name" class="aprd-cpc-chart-item">
                <div class="aprd-cpc-chart-title">{{ item.name }}</div>
                <div class="aprd-cpc-chart" :ref="(el) => (cpcChartRefs[index] = el)"></div>
              </div>
            </div>
          </div>

          <!-- 右侧图表 -->
          <div class="aprd-right-charts">
            <!-- 图表选择器 -->
            <div class="aprd-chart-selector">
              <div class="aprd-selector-header">
                <span class="aprd-selector-title">图表选择</span>
                <!-- <el-input
                  v-model="chartSearchText"
                  placeholder="搜索图表名称"
                  size="small"
                  clearable
                  style="width: 200px;"
                >
                  <template #prefix>
                    <el-icon><Search /></el-icon>
                  </template>
                </el-input> -->
              </div>
              <el-select
                v-model="selectedCharts"
                multiple
                placeholder="请选择要显示的图表"
                size="small"
                style="width: 100%;"
                :filterable="true"
                :filter-method="filterCharts"
                collapse-tags
                collapse-tags-tooltip
                :max-collapse-tags="3"
              >
                <el-option
                  v-for="chart in filteredChartOptions"
                  :key="chart.value"
                  :label="chart.label"
                  :value="chart.value"
                />
              </el-select>
            </div>
            
            <!-- 动态图表容器 -->
            <div class="aprd-dynamic-charts">
              <div
                v-for="chartId in selectedCharts"
                :key="chartId"
                class="aprd-chart-item"
                :class="{ 'aprd-chart-item-large': chartId === 'app7' }"
              >
                <div class="aprd-chart-title">{{ getChartTitle(chartId) }}</div>
                <div 
                  class="aprd-chart" 
                  :class="{ 'aprd-chart-large': chartId === 'app7' }"
                  :id="chartId"
                ></div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <template #footer>
        <span class="dialog-footer">
          <el-button @click="detailDialogVisible = false" size="small">关闭</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted, computed, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { Search } from '@element-plus/icons-vue';
import * as echarts from 'echarts/core';
import { LineChart, HeatmapChart } from 'echarts/charts';
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  MarkLineComponent,
  ToolboxComponent,
  DataZoomComponent,
  VisualMapComponent,
} from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';
import type { EChartsOption } from 'echarts';
import { ActualPerformanceRollDeviationApi } from '/@/api/deviationanalysis/ActualPerformanceRollDeviation';
import { historyApi } from '/@/api/furnaceTempDynamicCtrl/history';
import { zincApi } from '/@/api/znpot/index';

// Register ECharts components
echarts.use([
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  MarkLineComponent,
  ToolboxComponent,
  DataZoomComponent,
  VisualMapComponent,
  LineChart,
  HeatmapChart,
  CanvasRenderer,
]);

// API 接口
// import { ActualPerformanceRollDeviationApi } from '/@/api/deviationanalysis/ActualPerformanceRollDeviation'; // 假设已定义

// 帮助函数：转换日期时间格式
const formatDateTimeForApi = (dateTimeStr: string | null | undefined): string | undefined => {
  if (!dateTimeStr) return undefined;
  // Input: "YYYY-MM-DD HH:mm:ss"
  // Output: "YYYY-MM-DD-HH.mm.ss.000000" (assuming 0 microseconds if not available)
  return dateTimeStr.replace(' ', '-') + '.000000';
};

const now = new Date();
const pad = (n: number) => n.toString().padStart(2, '0');
// 计算一周前的时间
const oneWeekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
const oneWeekAgoStr = `${oneWeekAgo.getFullYear()}-${pad(oneWeekAgo.getMonth() + 1)}-${pad(oneWeekAgo.getDate())} ${pad(oneWeekAgo.getHours())}:${pad(
  oneWeekAgo.getMinutes()
)}:${pad(oneWeekAgo.getSeconds())}`;
const currentDateTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(
  now.getMinutes()
)}:${pad(now.getSeconds())}`;

// 搜索参数
const searchParams = reactive({
  startTime: oneWeekAgoStr, // 一周前
  endTime: currentDateTime, // 当前时间
  parentCoilNo: '', // -> matIdent
  exitCoilNo: '', // -> extid
  widthBin: '', // -> widthCode
  exitThicknessBin: '', // -> thickCode
  steelGradeBin: '', // -> gradeCode
  paopianFlagTrue: '', // -> paopianFlagTrue (是否跑偏: ''全部, '0'不跑偏, '1'跑偏)
});

// 分页相关
const currentPage = ref(1);
const pageSize = ref(20); // 默认分页大小为20
const totalItems = ref(0); // 初始化为0，从API获取

// 表头样式
const headerStyle = {
  background: '#eef1f6',
  color: '#606266',
};

// 表格数据 (将由API填充)
const tableData = reactive<any[]>([]);

// 详情弹窗
const detailDialogVisible = ref(false);

// 图表选择相关
const selectedCharts = ref<string[]>(['app7', 'app11', 'app_combined']); // 默认选择前三个
const chartSearchText = ref('');

// 所有可用的图表选项
const chartOptions = [
  { value: 'app7', label: '板形仪通道号(长度序列)' },
  { value: 'app11', label: '5机架速度(m/min)' },
  { value: 'app_combined', label: '生产过程追溯（张力差/轧制力差/倾斜）' },
  { value: 'process_temp_chart', label: '温度曲线' },
  { value: 'process_tension_chart', label: '张力曲线' },
  { value: 'process_speed_chart', label: '速度曲线' },
  { value: 'process_looper_chart', label: '活套曲线' },
  { value: 'app_priterm', label: '一次项系数DS-OS' }
];

// 过滤后的图表选项
const filteredChartOptions = computed(() => {
  if (!chartSearchText.value) {
    return chartOptions;
  }
  return chartOptions.filter(chart => 
    chart.label.toLowerCase().includes(chartSearchText.value.toLowerCase())
  );
});

// 获取图表标题
const getChartTitle = (chartId: string) => {
  const chart = chartOptions.find(c => c.value === chartId);
  return chart ? chart.label : chartId;
};

// 过滤图表方法
const filterCharts = (query: string) => {
  chartSearchText.value = query;
};

const detailData = reactive({
  // Structure for detail data based on API response + existing fields
  extid: '', // 出口卷号 (from exitCoilNo)
  steelGrade: '',
  width: null as number | null, // 出口宽度 (from exitWidth)
  thick: null as number | null, // 出口厚度 (from exitThickness)
  length: null as number | null,
  paopianRate: null as number | null, // 预测跑偏概率 (from deviationProb)
  paopianFlagTrue: null as number | null, // 是否跑偏 (from stripDeviation mapped to paopianFlagTrue)
  prodEndTime: '', // 创建时间 (from time)
  shiftNo: null as number | null, // 班次 (from shift)
  gradeCode: null as number | null, // 钢种分档 (from steelGradeBin)
  widthCode: null as number | null, // 宽度分档 (from widthBin)
  thickCode: null as number | null, // 出口厚度分档 (from exitThicknessBin)

  // Fields from API to add to detail view
  entryThick: null as number | null,
  entryWidth: null as number | null,
  entryLength: null as number | null, // Assuming entryLength is also needed if entryThick/Width are
  hotCoilId: '',
  paopianFlag: null as number | null, //纠偏满载

  // Analysis section fields - map from API or keep mock if necessary
  isSpecialSteel: false, // Keep mock or remove if not derivable
  historyRisk: 0, // Keep mock or remove
  hotRollCondition: '良好', // Keep mock or remove
  c40Passrate: null as number | string | null, // 凸度命中率 (from convexityRate)
  w40Passrate: null as number | string | null, // 楔形命中率 (from wedgeRate)

  // Chart data arrays (mock generation logic remains for now)
  cpcData: [] as { x: number[]; ds: number[]; os: number[] }[],
  convexityWedgeData: { x: [] as number[], c40: [] as number[], w40: [] as number[], upper: [] as number[], lower: [] as number[] },
  processTraceData: { x: [] as number[], tensionDiff1: [] as number[], tensionDiff2: [] as number[], speed: [] as number[] },
  
  // 工艺参数曲线数据
  processCurveData: {} as any,
  // 索引签名，允许通过字符串索引访问所有字段
} as Record<string, any>);

// Chart Refs
const cpcChartRefs = ref<any[]>([]);
const convexityWedgeChartRef = ref<HTMLElement | null>(null);
const processTraceChartRef = ref<HTMLElement | null>(null);

// Chart Instances
let cpcChartInstances: (echarts.ECharts | null)[] = [];
let convexityWedgeChartInstance: echarts.ECharts | null = null;
let processTraceChartInstance: echarts.ECharts | null = null;
let cpcBigChartInstance: echarts.ECharts | null = null;

// 右侧图表实例
let tensionChartInstance: echarts.ECharts | null = null; // deprecated combined
let speedChartInstance: echarts.ECharts | null = null;
let forceChartInstance: echarts.ECharts | null = null; // deprecated combined
let tiltChartInstance: echarts.ECharts | null = null; // deprecated combined
let shapeChartInstance: echarts.ECharts | null = null;
let priTermChartInstance: echarts.ECharts | null = null;

// 新增：组合图实例
let combinedChartInstance: echarts.ECharts | null = null;

// 工艺参数曲线图表实例
let processTempChartInstance: echarts.ECharts | null = null;
let processTensionChartInstance: echarts.ECharts | null = null;
let processSpeedChartInstance: echarts.ECharts | null = null;
let processLooperChartInstance: echarts.ECharts | null = null;

// --- 事件处理函数 ---
const handleSearch = async () => {
  // ElMessage.success('执行查询'); // Replaced by API call
  console.log('查询参数:', searchParams);
  const payload = {
    page: {
      pageIndex: currentPage.value,
      pageSize: pageSize.value,
    },
    dto: {
      extid: searchParams.exitCoilNo || undefined,
      matIdent: searchParams.parentCoilNo || undefined,
      gradeCode: searchParams.steelGradeBin ? Number(searchParams.steelGradeBin) : undefined,
      startTime: formatDateTimeForApi(searchParams.startTime),
      endTime: formatDateTimeForApi(searchParams.endTime),
      thickCode: searchParams.exitThicknessBin ? Number(searchParams.exitThicknessBin) : undefined,
      widthCode: searchParams.widthBin ? Number(searchParams.widthBin) : undefined,
      paopianFlagTrue: searchParams.paopianFlagTrue !== '' ? Number(searchParams.paopianFlagTrue) : undefined,
    },
  };
  // Remove undefined keys from dto to avoid sending empty parameters
  Object.keys(payload.dto).forEach((key) => {
    if (payload.dto[key as keyof typeof payload.dto] === undefined) {
      delete payload.dto[key as keyof typeof payload.dto];
    }
  });

  try {
    const apiResponse = await ActualPerformanceRollDeviationApi.findByPage(payload);
    console.log('回调参数', apiResponse);

    // Assuming apiResponse is the full AxiosResponse, so data is in apiResponse.data
    // And the actual records and total are in response.data.data according to the new log
    if (apiResponse && apiResponse.data && apiResponse.data.data && Array.isArray(apiResponse.data.data.records)) {
      const responsePayload = apiResponse.data; // Outer payload with msg, status, nested data
      const actualData = responsePayload.data; // Nested data with records, total, etc.

      tableData.splice(0, tableData.length);

      actualData.records.forEach((record: any, index: number) => {
        const newRow: any = {
          seqNo: (currentPage.value - 1) * pageSize.value + index + 1,
          // Map fields from record (camelCase from API) to tableData fields
          exitCoilNo: record.extid,
          parentCoilNo: record.matIdent,
          steelGrade: record.steelGrade,
          exitWidth: record.width,
          exitThickness: record.thick,
          length: record.length,
          deviationProb: record.paopianRate,
          stripDeviation: record.paopianFlagTrue, // paopianFlagTrue seems to be the 'is deviation' flag
          time: record.prodEndTime ? new Date(record.prodEndTime).toLocaleString() : '-', // Format timestamp
          shift: record.shiftNo,
          steelGradeBin: record.gradeCode,
          widthBin: record.widthCode,
          exitThicknessBin: record.thickCode,
          // Keep the rest of the record data for the detail view
          ...record,
        };
        // Map cpcXStripMax/Avg correctly
        for (let i = 1; i <= 10; i++) {
          // Use optional chaining and nullish coalescing for safety
          newRow['max_strip' + i] = record?.[`cpc${i}StripMax`] ?? null;
          newRow['avg_strip' + i] = record?.[`cpc${i}StripAvg`] ?? null;
        }
        tableData.push(newRow);
      });
      // Use total from the nested data object
      totalItems.value = actualData.total || 0;
      // Use msg from the outer responsePayload object
      ElMessage.success(responsePayload.msg || '查询成功');
    } else {
      // Handle cases where apiResponse.data.data or apiResponse.data.data.records might be missing
      const errorMessage = apiResponse?.data?.msg || '查询失败，数据结构不正确或无记录';
      ElMessage.error(errorMessage);
      tableData.splice(0, tableData.length);
      totalItems.value = 0;
    }
  } catch (error: any) {
    console.error('API call failed:', error);
    // Attempt to get a message from error.response.data.msg if it's an API error
    const anError = error as any;
    const apiErrorMessage =
      anError.response && anError.response.data && anError.response.data.msg
        ? anError.response.data.msg
        : anError.msg || anError.message || '查询接口调用失败';
    ElMessage.error(apiErrorMessage);
    tableData.splice(0, tableData.length);
    totalItems.value = 0;
  }
};

const handleReset = () => {
  // 重新计算一周前的时间
  const now = new Date();
  const oneWeekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
  searchParams.startTime = `${oneWeekAgo.getFullYear()}-${pad(oneWeekAgo.getMonth() + 1)}-${pad(oneWeekAgo.getDate())} ${pad(oneWeekAgo.getHours())}:${pad(
    oneWeekAgo.getMinutes()
  )}:${pad(oneWeekAgo.getSeconds())}`;
  searchParams.endTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(
    now.getMinutes()
  )}:${pad(now.getSeconds())}`;
  searchParams.parentCoilNo = '';
  searchParams.exitCoilNo = '';
  searchParams.widthBin = '';
  searchParams.exitThicknessBin = '';
  searchParams.steelGradeBin = '';
  searchParams.paopianFlagTrue = '';
  currentPage.value = 1;
  handleSearch(); // Optionally re-fetch data with default/empty params
  ElMessage.info('重置搜索条件');
};

const handleExport = async () => {
  try {
    ElMessage.info('正在导出，请稍候...');

    const payload = {
      page: {
        pageIndex: currentPage.value,
        pageSize: pageSize.value,
      },
      dto: {
        extid: searchParams.exitCoilNo || undefined,
        matIdent: searchParams.parentCoilNo || undefined,
        gradeCode: searchParams.steelGradeBin ? Number(searchParams.steelGradeBin) : undefined,
        startTime: formatDateTimeForApi(searchParams.startTime),
        endTime: formatDateTimeForApi(searchParams.endTime),
        thickCode: searchParams.exitThicknessBin ? Number(searchParams.exitThicknessBin) : undefined,
        widthCode: searchParams.widthBin ? Number(searchParams.widthBin) : undefined,
        paopianFlagTrue: searchParams.paopianFlagTrue !== '' ? Number(searchParams.paopianFlagTrue) : undefined,
      },
    };

    // Remove undefined keys from dto
    Object.keys(payload.dto).forEach((key) => {
      if (payload.dto[key as keyof typeof payload.dto] === undefined) {
        delete payload.dto[key as keyof typeof payload.dto];
      }
    });

    await ActualPerformanceRollDeviationApi.exportXlsx(payload);
    ElMessage.success('导出成功');
  } catch (error: any) {
    console.error('导出失败:', error);
    const errorMessage = error?.response?.data?.msg || error?.msg || error?.message || '导出失败';
    ElMessage.error(errorMessage);
  }
};
const handleSizeChange = (val: number) => {
  pageSize.value = val;
  currentPage.value = 1; // Reset to first page when size changes
  handleSearch();
  console.log(`每页 ${val} 条`);
};
const handleCurrentChange = (val: number) => {
  currentPage.value = val;
  handleSearch();
  console.log(`当前页: ${val}`);
};

const cpcChartNames = [
  'CPC1',
  'CPC2',
  'CPC3',
  'CPC4',
  'CPC5',
  'CPC6',
  'CPC7',
  'CPC8',
  'CPC9-0',
  'CPC9-1',
  'CPC9-2',
  'CPC9-3',
  'CPC9-4',
  'CPC9-5',
  'CPC9-6',
  'CPC9-7',
  'CPC9-8',
  'CPC10',
  'CPC11',
  'CPC12',
  'CPC13',
  'CPC14',
  'CPC15',
  'CPC16',
  'CPC17',
  'EPC1',
  'EPC2',
];
const cpcDataKeys = [
  'cal_cpc1',
  'cal_cpc2',
  'cal_cpc3',
  'cal_cpc4',
  'cal_cpc5',
  'cal_cpc6',
  'cal_cpc7',
  'cal_cpc8',
  'cal_cpc9_0',
  'cal_cpc9_1',
  'cal_cpc9_2',
  'cal_cpc9_3',
  'cal_cpc9_4',
  'cal_cpc9_5',
  'cal_cpc9_6',
  'cal_cpc9_7',
  'cal_cpc9_8',
  'cal_cpc10',
  'cal_cpc11',
  'cal_cpc12',
  'cal_cpc13',
  'cal_cpc14',
  'cal_cpc15',
  'cal_cpc16',
  'cal_cpc17',
  'cal_epc1',
  'cal_epc2',
];

function generateFakeData(idx: number, len = 100) {
  const base = Array(len)
    .fill(0)
    .map((_, i) => i);
  const hcpos = base.map(
    (i) => Math.sin(i / (8 + idx)) * (40 + idx * 2) + Math.cos(i / (3 + (idx % 5))) * (10 + idx) + (Math.random() - 0.5) * 10 * (1 + (idx % 3))
  );
  const strippos = base.map(
    (i) =>
      Math.cos(i / (7 + idx)) * (30 + idx * 3) + Math.sin(i / (2 + (idx % 4))) * (15 + idx) + (Math.random() - 0.5) * 12 * (1 + ((idx + 1) % 4))
  );
  return { hcpos, strippos };
}

// 根据卷号前缀分组
const getGroupedCoils = (currentCoil: string) => {
  // 提取前缀，去掉最后3位数字
  const prefix = currentCoil.replace(/\d{3}$/, '');
  console.log('当前卷号前缀:', prefix);
  
  // 查找所有具有相同前缀的卷号
  const groupedCoils = tableData.filter(row => 
    row.extid && row.extid.startsWith(prefix) && row.extid !== currentCoil
  );
  
  // 将当前卷号也加入组中
  const allGroupedCoils = [currentCoil, ...groupedCoils.map(row => row.extid)];
  
  console.log('分组结果:', {
    当前卷号: currentCoil,
    前缀: prefix,
    同组卷号: allGroupedCoils,
    组内数量: allGroupedCoils.length
  });
  
  return allGroupedCoils;
};

// 合并多组CPC数据
const mergeCpcData = (allCpcData: any[][]) => {
  if (allCpcData.length === 0) return [];
  
  const mergedData: any[] = [];
  const cpcCount = allCpcData[0].length;
  
  for (let i = 0; i < cpcCount; i++) {
    const cpcName = allCpcData[0][i].name;
    const mergedCpc = {
      name: cpcName,
      x: [] as number[],
      hcpos: [] as number[],
      hcpos1: [] as number[],
      hcpos2: [] as number[],
      strippos: [] as number[]
    };
    
    // 合并所有组的数据
    allCpcData.forEach(groupData => {
      if (groupData[i]) {
        const cpc = groupData[i];
        if (cpcName.startsWith('CPC9-')) {
          // CPC9系列有三条线
          mergedCpc.x = [...mergedCpc.x, ...cpc.x];
          mergedCpc.hcpos1 = [...mergedCpc.hcpos1, ...cpc.hcpos1];
          mergedCpc.hcpos2 = [...mergedCpc.hcpos2, ...cpc.hcpos2];
          mergedCpc.strippos = [...mergedCpc.strippos, ...cpc.strippos];
        } else if (cpcName.startsWith('EPC')) {
          // EPC系列有两条线
          mergedCpc.x = [...mergedCpc.x, ...cpc.x];
          mergedCpc.hcpos = [...mergedCpc.hcpos, ...cpc.hcpos];
          mergedCpc.strippos = [...mergedCpc.strippos, ...cpc.strippos];
        } else {
          // 其他CPC系列有两条线
          mergedCpc.x = [...mergedCpc.x, ...cpc.x];
          mergedCpc.hcpos = [...mergedCpc.hcpos, ...cpc.hcpos];
          mergedCpc.strippos = [...mergedCpc.strippos, ...cpc.strippos];
        }
      }
    });
    
    mergedData.push(mergedCpc);
  }
  
  console.log('合并后的CPC数据:', mergedData);
  return mergedData;
};

const showDetail = async (row: any) => {
  // Assign API data to detailData
  detailData.extid = row.extid; // 出口卷号
  detailData.entid = row.entid; // 入口卷号（重要！用于查询图表数据）
  detailData.steelGrade = row.steelGrade;
  detailData.width = row.width;
  detailData.thick = row.thick;
  detailData.length = row.length;
  detailData.paopianRate = row.paopianRate;
  detailData.paopianFlagTrue = row.paopianFlagTrue; // 0 or 1
  // Format timestamp in detail view as well
  detailData.prodEndTime = row.prodEndTime;
  // row.time instanceof Date ? row.time.toLocaleString() : typeof row.time === 'number' ? new Date(row.time).toLocaleString() : row.time ?? '-'; // Handle if already string or null/undefined
  detailData.shiftNo = row.shiftNo;
  detailData.gradeCode = row.gradeCode;
  detailData.widthCode = row.widthCode;
  detailData.thickCode = row.thickCode; //出口厚度分档号

  detailData.entryThick = row.entryThick;
  detailData.entryWidth = row.entryWidth;
  detailData.entryLength = row.entryLength; // Assuming API provides this or it's derived
  detailData.hotCoilId = row.hotCoilId;
  detailData.paopianFlag = row.paopianFlag; //纠偏满载

  // For "跑偏原因智能分析" section
  // These are kept as mock or need specific logic if not directly from 'row'
  detailData.isSpecialSteel = row.extid && row.extid.includes('SP') ? true : false; // Example mock logic
  detailData.historyRisk = row.paopianRate !== null ? Math.round(row.paopianRate / 10) : 0; // Example mock logic
  detailData.hotRollCondition = (row.thickCode || 0) > 1 ? '一般' : '良好'; // Example mock logic
  detailData.c40Passrate = row.c40Passrate; //凸度命中率
  detailData.w40Passrate = row.w40Passrate; //楔形命中率

  // 新增：调用query接口获取工艺参数曲线数据
  const queryParams = {
    line: 'CAL1630',
    extid: row.extid,
    curve: [
      'cal_preheat_strip_temp',
      'cal_heat_strip_temp',
      'cal_enlooper_precent',
      'cal_preheat_fur_temp',
      'cal_heat_fur_z1_2_temp',
      'cal_heat_fur_z3_4_temp',
      'cal_heat_fur_z5_6_temp',
      'cal_heat_fur_z7_8_temp',
      'cal_heat_fur_z9_10_temp',
      'cal_heat_fur_z11_12_temp',
      'cal_heat1_ten_set',
      'cal_heat1_ten',
      'cal_heat2_ten_set',
      'cal_heat2_ten',
      'cal_process_speed',
      'cal_preheat_ten',
      'cal_preheat_ten_set'
    ],
    "kv": [
      "tcm_s4 torque_act avg", "tcm_cpc10 pos_ std"],
    "pdo": ["S5 FORCE", "platetype"],
    "pdi": [],"model": ["test"]
  };
  console.log('========== 开始调用query接口 ==========');
  console.log('✅ 请求参数:', queryParams);
  const queryRes = await zincApi.getGraph(queryParams);
  console.log('✅ query接口返回值:', queryRes);
  console.log('✅ queryRes.data:', queryRes?.data);
  console.log('✅ queryRes.data.data:', queryRes?.data?.data);
  console.log('========== query接口调用完成 ==========');

  // 保存工艺参数曲线数据
  if (queryRes?.data?.data?.curve) {
    detailData.processCurveData = queryRes.data.data.curve;
    console.log('✅ 保存工艺参数曲线数据:', detailData.processCurveData);
  }

  // 获取同组的所有卷号
  const groupedCoils = getGroupedCoils(row.extid);
  console.log('========== 开始处理同组卷号数据 ==========');
  console.log('同组卷号列表:', groupedCoils);

  // 为每个卷号调用querytheme接口
  const allCpcData: any[][] = [];
  
  for (const coilId of groupedCoils) {
    console.log(`处理卷号: ${coilId}`);
    const params = {
      line: 'CAL1630',
      extid: coilId,
      theme_group_id: 'PAOPIAN_RES',
    };
    
    try {
      const themeRes = await ActualPerformanceRollDeviationApi.querytheme(params);
      console.log(`${coilId} 的theme数据:`, themeRes);
      
      const cpcData: any[] = [];
      for (let i = 0; i < cpcChartNames.length; i++) {
        const key = cpcDataKeys[i];
        if (key.startsWith('cal_cpc9_')) {
          // 三条线
          let hcpos1 = themeRes.data.data?.curve[`${key}_1_hcpos`];
          let hcpos2 = themeRes.data.data?.curve[`${key}_2_hcpos`];
          let strippos = themeRes.data.data?.curve[`${key}_strippos`];
          if (!hcpos1 || !hcpos2 || !strippos) {
            const fake = generateFakeData(i, 100);
            hcpos1 = fake.hcpos;
            hcpos2 = fake.hcpos.map((v) => v * 0.8);
            strippos = fake.strippos;
          }
          cpcData.push({
            name: cpcChartNames[i],
            x: strippos.map((_: any, idx: number) => idx),  // X轴从0开始
            hcpos1,
            hcpos2,
            strippos,
          });
        } else if (key.startsWith('cal_epc')) {
          // epc1/2
          let hcpos = themeRes.data.data?.curve[`${key}_hcpos`];
          let strippos = themeRes.data.data?.curve[`${key}_strippos`];
          if (!hcpos || !strippos) {
            const fake = generateFakeData(i, 100);
            hcpos = fake.hcpos;
            strippos = fake.strippos;
          }
          cpcData.push({
            name: cpcChartNames[i],
            x: hcpos.map((_: any, idx: number) => idx),  // X轴从0开始
            hcpos,
            strippos,
          });
        } else {
          // 其它CPC
          let hcpos = themeRes.data.data?.curve[`${key}_hcpos`];
          let strippos = themeRes.data.data?.curve[`${key}_strippos`];
          if (!hcpos || !strippos) {
            const fake = generateFakeData(i, 100);
            hcpos = fake.hcpos;
            strippos = fake.strippos;
          }
          cpcData.push({
            name: cpcChartNames[i],
            x: hcpos.map((_: any, idx: number) => idx),  // X轴从0开始
            hcpos,
            strippos,
          });
        }
      }
      allCpcData.push(cpcData);
    } catch (error) {
      console.error(`处理卷号 ${coilId} 时出错:`, error);
      // 如果某个卷号失败，使用假数据
      const fakeCpcData: any[] = [];
      for (let i = 0; i < cpcChartNames.length; i++) {
        const fake = generateFakeData(i, 100);
        if (cpcChartNames[i].startsWith('CPC9-')) {
          fakeCpcData.push({
            name: cpcChartNames[i],
            x: Array.from({ length: 100 }, (_, idx) => idx),  // X轴从0开始
            hcpos1: fake.hcpos,
            hcpos2: fake.hcpos.map((v) => v * 0.8),
            strippos: fake.strippos,
          });
        } else {
          fakeCpcData.push({
            name: cpcChartNames[i],
            x: Array.from({ length: 100 }, (_, idx) => idx),  // X轴从0开始
            hcpos: fake.hcpos,
            strippos: fake.strippos,
          });
        }
      }
        allCpcData.push(fakeCpcData);
    }
  }
  
  // 合并所有组的CPC数据
  detailData.cpcData = mergeCpcData(allCpcData);
  console.log('========== 同组卷号数据处理完成 ==========');
  console.log('最终合并的CPC数据:', detailData.cpcData);
  
  detailDialogVisible.value = true;
};

// 获取右侧图表数据 - 使用与 PlanRollDeviationPrediction.vue 相同的方式
const fetchRightChartsData = async (inMatNo: string) => {
  try {
    // 使用 historyApi.getgraphData 接口，和 PlanRollDeviationPrediction.vue 一致
    const params = [
      'tcm_s4s5_ten_diff',      // 5机架张力差
      'tcm_s5_strip_speed_act', // 速度
      'tcm_s5_force_diff',      // 5机架轧制力差
      'tcm_s5_tilt_act',        // S5机架倾斜
      // 板形数据 (0-63通道)
      'tcm_shape_channe_0', 'tcm_shape_channe_1', 'tcm_shape_channe_2', 'tcm_shape_channe_3',
      'tcm_shape_channe_4', 'tcm_shape_channe_5', 'tcm_shape_channe_6', 'tcm_shape_channe_7',
      'tcm_shape_channe_8', 'tcm_shape_channe_9', 'tcm_shape_channe_10', 'tcm_shape_channe_11',
      'tcm_shape_channe_12', 'tcm_shape_channe_13', 'tcm_shape_channe_14', 'tcm_shape_channe_15',
      'tcm_shape_channe_16', 'tcm_shape_channe_17', 'tcm_shape_channe_18', 'tcm_shape_channe_19',
      'tcm_shape_channe_20', 'tcm_shape_channe_21', 'tcm_shape_channe_22', 'tcm_shape_channe_23',
      'tcm_shape_channe_24', 'tcm_shape_channe_25', 'tcm_shape_channe_26', 'tcm_shape_channe_27',
      'tcm_shape_channe_28', 'tcm_shape_channe_29', 'tcm_shape_channe_30', 'tcm_shape_channe_31',
      'tcm_shape_channe_32', 'tcm_shape_channe_33', 'tcm_shape_channe_34', 'tcm_shape_channe_35',
      'tcm_shape_channe_36', 'tcm_shape_channe_37', 'tcm_shape_channe_38', 'tcm_shape_channe_39',
      'tcm_shape_channe_40', 'tcm_shape_channe_41', 'tcm_shape_channe_42', 'tcm_shape_channe_43',
      'tcm_shape_channe_44', 'tcm_shape_channe_45', 'tcm_shape_channe_46', 'tcm_shape_channe_47',
      'tcm_shape_channe_48', 'tcm_shape_channe_49', 'tcm_shape_channe_50', 'tcm_shape_channe_51',
      'tcm_shape_channe_52', 'tcm_shape_channe_53', 'tcm_shape_channe_54', 'tcm_shape_channe_55',
      'tcm_shape_channe_56', 'tcm_shape_channe_57', 'tcm_shape_channe_58', 'tcm_shape_channe_59',
      'tcm_shape_channe_60', 'tcm_shape_channe_61', 'tcm_shape_channe_62', 'tcm_shape_channe_63'
    ];

    const graphParam = {
      line: 'TCM2280',        // 使用 TCM2280 生产线
      extid: [inMatNo],       // ✅ 使用入口卷号（与 PlanRollDeviationPrediction.vue 一致）
      curve: params,          // 要查询的曲线参数
    };

    console.log('✅ 请求参数（使用入口卷号）:', graphParam);
    const response = await historyApi.getgraphData(graphParam);
    console.log('右侧图表原始数据:', response);

    // 数据结构: response.data.data.curve[0]
    const curveData = response?.data?.data?.curve?.[0] || {};

    return {
      curveData: curveData
    };
  } catch (error) {
    console.error('获取右侧图表数据失败:', error);
    return { curveData: null };
  }
};

// 保存一次项系数数据的引用
let cachedPriTermData: any = null;

// 获取一次项系数数据 - 使用 model 参数（与 LayOutJudge.vue 一致）
const fetchPriTermData = async (inMatNo: string) => {
  try {
    const modelParams = [
      'flatave',
      'flatave_positive',
      'PriTerm',      // 一次项系数
      'QuaTerm'       // 二次项系数
    ];

    const graphParam = {
      line: 'TCM2280',
      extid: [inMatNo],
      model: modelParams,
    };

    const response = await historyApi.getgraphData(graphParam);

    // 数据结构: response.data.data.model[0]
    const modelData = response?.data?.data?.model?.[0] || {};

    // 缓存数据
    if (modelData && modelData.PriTerm) {
      cachedPriTermData = modelData;
    }

    return {
      modelData: modelData
    };
  } catch (error) {
    console.error('❌ 获取一次项系数数据失败:', error);
    return { modelData: null };
  }
};

// --- Chart Initialization ---

const initDetailCharts = () => {
  disposeCharts();
  cpcChartInstances = [];
  for (let index = 0; index < cpcChartNames.length; index++) {
    const ref = cpcChartRefs.value[index];
    if (ref && detailData.cpcData[index]) {
      const showXAxisLabel = cpcChartNames[index] === 'EPC2';
      let cpcOption;
      if (cpcChartNames[index].startsWith('CPC9-')) {
        // 三条线
        cpcOption = {
          tooltip: { trigger: 'axis' },
          grid: { left: '10%', right: '5%', top: '10%', bottom: '15%' },
          xAxis: {
            type: 'category',
            boundaryGap: false,
            data: detailData.cpcData[index].x,
            axisLabel: { fontSize: 10, show: showXAxisLabel },
          },
          yAxis: {
            type: 'value',
            min: -100,
            max: 100,
            axisLabel: { fontSize: 10 },
          },
          series: [
            {
              name: '缸1',
              type: 'line',
              smooth: true,
              symbol: 'none',
              data: detailData.cpcData[index].hcpos1,
              lineStyle: { color: '#5470C6' },
            },
            {
              name: '缸2',
              type: 'line',
              smooth: true,
              symbol: 'none',
              data: detailData.cpcData[index].hcpos2,
              lineStyle: { color: '#91CC75' },
            },
            {
              name: '带钢',
              type: 'line',
              smooth: true,
              symbol: 'none',
              data: detailData.cpcData[index].strippos,
              lineStyle: { color: '#FFD600' },
            },
          ],
        };
      } else {
        // 两条线
        cpcOption = {
          tooltip: { trigger: 'axis' },
          grid: { left: '10%', right: '5%', top: '10%', bottom: '15%' },
          xAxis: {
            type: 'category',
            boundaryGap: false,
            data: detailData.cpcData[index].x,
            axisLabel: { fontSize: 10, show: showXAxisLabel },
          },
          yAxis: {
            type: 'value',
            min: -100,
            max: 100,
            axisLabel: { fontSize: 10 },
          },
          series: [
            {
              name: '纠偏缸位置',
              type: 'line',
              smooth: true,
              symbol: 'none',
              data: detailData.cpcData[index].hcpos,
              lineStyle: { color: '#5470C6' },
            },
            {
              name: '带钢位置',
              type: 'line',
              smooth: true,
              symbol: 'none',
              data: detailData.cpcData[index].strippos,
              lineStyle: { color: '#FFD600' },
            },
          ],
        };
      }
      const chart = echarts.init(ref);
      chart.setOption(cpcOption);
      chart.resize();
      cpcChartInstances.push(chart);
    }
  }
  // Init Convexity/Wedge Chart
  if (convexityWedgeChartRef.value) {
    convexityWedgeChartInstance = echarts.init(convexityWedgeChartRef.value);
    const cwOption: EChartsOption = {
      tooltip: { trigger: 'axis' },
      legend: {
        data: ['凸度曲线-C40', '楔形曲线-W40'],
        bottom: 5,
        textStyle: { fontSize: 10 },
      },
      grid: { left: '10%', right: '8%', top: '10%', bottom: '20%' },
      xAxis: {
        type: 'category',
        boundaryGap: false,
        data: detailData.convexityWedgeData.x,
        name: '(m)', // X-axis name
        nameLocation: 'end',
        axisLabel: { fontSize: 10 },
      },
      yAxis: {
        type: 'value',
        name: 'μm', // Y-axis name
        axisLabel: { fontSize: 10 },
        // Consider min/max based on data or image
      },
      series: [
        {
          name: '凸度曲线-C40',
          type: 'line',
          smooth: true,
          symbol: 'none',
          data: detailData.convexityWedgeData.c40,
          lineStyle: { color: '#5470C6' },
          markLine: {
            symbol: ['none', 'none'],
            label: { show: true, position: 'end', formatter: '上限' },
            data: [{ yAxis: 50 }], // Example upper limit
            lineStyle: { type: 'dashed', color: '#F56C6C' },
          },
        },
        {
          name: '楔形曲线-W40',
          type: 'line',
          smooth: true,
          symbol: 'none',
          data: detailData.convexityWedgeData.w40,
          lineStyle: { color: '#EE6666' },
          markLine: {
            symbol: ['none', 'none'],
            label: { show: true, position: 'end', formatter: '下限' },
            data: [{ yAxis: -40 }], // Example lower limit
            lineStyle: { type: 'dashed', color: '#F56C6C' },
          },
        },
      ],
    };
    convexityWedgeChartInstance.setOption(cwOption);
  }

  // Init Process Trace Chart
  if (processTraceChartRef.value) {
    processTraceChartInstance = echarts.init(processTraceChartRef.value);
    const ptOption: EChartsOption = {
      tooltip: { trigger: 'axis' },
      legend: {
        data: ['5机张力差', '5机张力差2', '5机出口速度'], // Names adjusted
        bottom: 5,
        textStyle: { fontSize: 10 },
      },
      grid: { left: '10%', right: '15%', top: '10%', bottom: '20%' }, // Adjust right for dual axis
      xAxis: {
        type: 'category',
        boundaryGap: false,
        data: detailData.processTraceData.x,
        axisLabel: { fontSize: 10 },
      },
      yAxis: [
        {
          type: 'value',
          name: 'KN', // Y-axis 1 name
          position: 'left',
          axisLabel: { fontSize: 10 },
          // Consider scale based on tension data
        },
        {
          type: 'value',
          name: 'm/min', // Y-axis 2 name
          position: 'right',
          axisLabel: { fontSize: 10 },
          // Consider scale based on speed data
        },
      ],
      series: [
        {
          name: '5机张力差',
          type: 'line',
          yAxisIndex: 0,
          smooth: true,
          symbol: 'none',
          data: detailData.processTraceData.tensionDiff1,
          lineStyle: { color: '#5470C6' },
        },
        {
          name: '5机张力差2', // Added second tension series
          type: 'line',
          yAxisIndex: 0,
          smooth: true,
          symbol: 'none',
          data: detailData.processTraceData.tensionDiff2,
          lineStyle: { color: '#91CC75' },
        },
        {
          name: '5机出口速度',
          type: 'line',
          yAxisIndex: 1,
          smooth: true,
          symbol: 'none',
          data: detailData.processTraceData.speed,
          lineStyle: { color: '#FAC858' },
        },
      ],
    };
    processTraceChartInstance.setOption(ptOption);
  }
};

// 渲染工艺参数曲线图表
const renderProcessCurveCharts = () => {
  if (!detailData.processCurveData || Object.keys(detailData.processCurveData).length === 0) {
    console.warn('工艺参数曲线数据为空');
    return;
  }

  console.log('开始渲染工艺参数曲线图表，数据:', detailData.processCurveData);

  // 温度曲线
  renderProcessTempChart();
  
  // 张力曲线
  renderProcessTensionChart();
  
  // 速度曲线
  renderProcessSpeedChart();
  
  // 活套曲线
  renderProcessLooperChart();
};

// 温度曲线渲染
const renderProcessTempChart = () => {
  const dom = document.getElementById('process_temp_chart');
  if (!dom) {
    console.error('process_temp_chart DOM元素不存在');
    return;
  }

  if (!processTempChartInstance) {
    processTempChartInstance = echarts.init(dom);
  }
  processTempChartInstance.clear();

  const series: any[] = [];
  const colors = ['#5470C6', '#91CC75', '#FAC858', '#EE6666', '#73C0DE', '#3BA272', '#FC8452', '#9A60B4', '#EA7CCC', '#DD6B66'];
  let colorIndex = 0;

  // 温度相关参数
  const tempParams = [
    { key: 'cal_preheat_strip_temp', name: '预热段带钢温度' },
    { key: 'cal_heat_strip_temp', name: '加热段带钢温度' },
    { key: 'cal_preheat_fur_temp', name: '预热段炉温' },
    { key: 'cal_heat_fur_z1_2_temp', name: '加热炉1-2区温度' },
    { key: 'cal_heat_fur_z3_4_temp', name: '加热炉3-4区温度' },
    { key: 'cal_heat_fur_z5_6_temp', name: '加热炉5-6区温度' },
    { key: 'cal_heat_fur_z7_8_temp', name: '加热炉7-8区温度' },
    { key: 'cal_heat_fur_z9_10_temp', name: '加热炉9-10区温度' },
    { key: 'cal_heat_fur_z11_12_temp', name: '加热炉11-12区温度' }
  ];

  tempParams.forEach(param => {
    const data = detailData.processCurveData[param.key];
    if (data && Array.isArray(data) && data.length > 0) {
      const xData = Array.from({ length: data.length }, (_, i) => i + 1);
      series.push({
        name: param.name,
        type: 'line',
        data: data.map((value: number, index: number) => [xData[index], value]),
        smooth: true,
        symbol: 'none',
        lineStyle: { color: colors[colorIndex % colors.length] }
      });
      colorIndex++;
    }
  });

  if (series.length === 0) {
    console.warn('温度曲线数据为空');
    return;
  }

  const option: EChartsOption = {
    tooltip: { trigger: 'axis' },
    legend: { data: series.map(s => s.name), bottom: 5, textStyle: { fontSize: 10 } },
    grid: { left: '10%', right: '8%', top: '10%', bottom: '20%' },
    xAxis: {
      type: 'category',
      name: '(m)',
      axisLabel: { fontSize: 10 }
    },
    yAxis: {
      type: 'value',
      name: '℃',
      axisLabel: { fontSize: 10 },
      scale: true
    },
    series
  };

  processTempChartInstance.setOption(option);
  console.log('✅ 温度曲线渲染完成');
};

// 张力曲线渲染
const renderProcessTensionChart = () => {
  const dom = document.getElementById('process_tension_chart');
  if (!dom) {
    console.error('process_tension_chart DOM元素不存在');
    return;
  }

  if (!processTensionChartInstance) {
    processTensionChartInstance = echarts.init(dom);
  }
  processTensionChartInstance.clear();

  const series: any[] = [];
  const colors = ['#5470C6', '#91CC75', '#FAC858', '#EE6666', '#73C0DE'];
  let colorIndex = 0;

  // 张力相关参数
  const tensionParams = [
    { key: 'cal_heat1_ten_set', name: '加热段1张力设定值' },
    { key: 'cal_heat1_ten', name: '加热段1张力实际值' },
    { key: 'cal_heat2_ten_set', name: '加热段2张力设定值' },
    { key: 'cal_heat2_ten', name: '加热段2张力实际值' },
    { key: 'cal_preheat_ten', name: '预热段张力实际值' },
    { key: 'cal_preheat_ten_set', name: '预热段张力设定值' }
  ];

  tensionParams.forEach(param => {
    const data = detailData.processCurveData[param.key];
    if (data && Array.isArray(data) && data.length > 0) {
      const xData = Array.from({ length: data.length }, (_, i) => i + 1);
      series.push({
        name: param.name,
        type: 'line',
        data: data.map((value: number, index: number) => [xData[index], value]),
        smooth: true,
        symbol: 'none',
        lineStyle: { color: colors[colorIndex % colors.length] }
      });
      colorIndex++;
    }
  });

  if (series.length === 0) {
    console.warn('张力曲线数据为空');
    return;
  }

  const option: EChartsOption = {
    tooltip: { trigger: 'axis' },
    legend: { data: series.map(s => s.name), bottom: 5, textStyle: { fontSize: 10 } },
    grid: { left: '10%', right: '8%', top: '10%', bottom: '20%' },
    xAxis: {
      type: 'category',
      name: '(m)',
      axisLabel: { fontSize: 10 }
    },
    yAxis: {
      type: 'value',
      name: 'kN',
      axisLabel: { fontSize: 10 },
      scale: true
    },
    series
  };

  processTensionChartInstance.setOption(option);
  console.log('✅ 张力曲线渲染完成');
};

// 速度曲线渲染
const renderProcessSpeedChart = () => {
  const dom = document.getElementById('process_speed_chart');
  if (!dom) {
    console.error('process_speed_chart DOM元素不存在');
    return;
  }

  if (!processSpeedChartInstance) {
    processSpeedChartInstance = echarts.init(dom);
  }
  processSpeedChartInstance.clear();

  const series: any[] = [];

  // 速度相关参数
  const speedParams = [
    { key: 'cal_process_speed', name: '炉内速度' }
  ];

  speedParams.forEach(param => {
    const data = detailData.processCurveData[param.key];
    if (data && Array.isArray(data) && data.length > 0) {
      const xData = Array.from({ length: data.length }, (_, i) => i + 1);
      series.push({
        name: param.name,
        type: 'line',
        data: data.map((value: number, index: number) => [xData[index], value]),
        smooth: true,
        symbol: 'none',
        lineStyle: { color: '#5470C6' }
      });
    }
  });

  if (series.length === 0) {
    console.warn('速度曲线数据为空');
    return;
  }

  const option: EChartsOption = {
    tooltip: { trigger: 'axis' },
    legend: { data: series.map(s => s.name), bottom: 5, textStyle: { fontSize: 10 } },
    grid: { left: '10%', right: '8%', top: '10%', bottom: '20%' },
    xAxis: {
      type: 'category',
      name: '(m)',
      axisLabel: { fontSize: 10 }
    },
    yAxis: {
      type: 'value',
      name: 'm/min',
      axisLabel: { fontSize: 10 },
      scale: true
    },
    series
  };

  processSpeedChartInstance.setOption(option);
  console.log('✅ 速度曲线渲染完成');
};

// 活套曲线渲染
const renderProcessLooperChart = () => {
  const dom = document.getElementById('process_looper_chart');
  if (!dom) {
    console.error('process_looper_chart DOM元素不存在');
    return;
  }

  if (!processLooperChartInstance) {
    processLooperChartInstance = echarts.init(dom);
  }
  processLooperChartInstance.clear();

  const series: any[] = [];

  // 活套相关参数
  const looperParams = [
    { key: 'cal_enlooper_precent', name: '活套套量' }
  ];

  looperParams.forEach(param => {
    const data = detailData.processCurveData[param.key];
    if (data && Array.isArray(data) && data.length > 0) {
      const xData = Array.from({ length: data.length }, (_, i) => i + 1);
      series.push({
        name: param.name,
        type: 'line',
        data: data.map((value: number, index: number) => [xData[index], value]),
        smooth: true,
        symbol: 'none',
        lineStyle: { color: '#91CC75' }
      });
    }
  });

  if (series.length === 0) {
    console.warn('活套曲线数据为空');
    return;
  }

  const option: EChartsOption = {
    tooltip: { trigger: 'axis' },
    legend: { data: series.map(s => s.name), bottom: 5, textStyle: { fontSize: 10 } },
    grid: { left: '10%', right: '8%', top: '10%', bottom: '20%' },
    xAxis: {
      type: 'category',
      name: '(m)',
      axisLabel: { fontSize: 10 }
    },
    yAxis: {
      type: 'value',
      name: '%',
      axisLabel: { fontSize: 10 },
      scale: true
    },
    series
  };

  processLooperChartInstance.setOption(option);
  console.log('✅ 活套曲线渲染完成');
};

// 初始化右侧图表 - 使用 tcm_ 前缀的字段（与 PlanRollDeviationPrediction.vue 一致）
const initRightCharts = async () => {
  // ✅ 使用入口卷号（entid）而不是出口卷号（extid）
  const inMatNo = detailData.entid || detailData.extid; // 优先使用入口卷号，如果没有则使用出口卷号作为后备
  console.log('✅ 使用卷号查询图表数据:', { entid: detailData.entid, extid: detailData.extid, 实际使用: inMatNo });

  const { curveData } = await fetchRightChartsData(inMatNo);

  console.log('右侧图表curve数据:', curveData);
  console.log('可用字段:', curveData ? Object.keys(curveData) : '无数据');

  if (!curveData || Object.keys(curveData).length === 0) {
    console.warn('未获取到右侧图表数据');
    return;
  }

  // 速度-长度序列 - 直接使用 tcm_ 前缀（保留独立图）
  if (curveData.tcm_s5_strip_speed_act && Array.isArray(curveData.tcm_s5_strip_speed_act) && curveData.tcm_s5_strip_speed_act.length > 0) {
    console.log('✓ 找到速度数据: tcm_s5_strip_speed_act, 长度:', curveData.tcm_s5_strip_speed_act.length);
    renderSpeedChart(curveData.tcm_s5_strip_speed_act);
  } else {
    console.log('✗ 速度数据为空或不存在');
  }

  // 合并张力差/轧制力差/倾斜为一个图
  const ten = Array.isArray(curveData.tcm_s4s5_ten_diff) ? curveData.tcm_s4s5_ten_diff : [];
  const force = Array.isArray(curveData.tcm_s5_force_diff) ? curveData.tcm_s5_force_diff : [];
  const tilt = Array.isArray(curveData.tcm_s5_tilt_act) ? curveData.tcm_s5_tilt_act : [];
  if (ten.length || force.length || tilt.length) {
    renderCombinedChart({ ten, force, tilt });
  } else {
    console.log('✗ 合并图数据为空');
  }

  // 板形仪通道号 - 查找所有 tcm_shape_channe_ 字段
  const shapeFields = Object.keys(curveData).filter(key =>
    key.startsWith('tcm_shape_channe_') && Array.isArray(curveData[key]) && curveData[key].length > 0
  );
  if (shapeFields.length > 0) {
    console.log(`✓ 找到板形数据，共 ${shapeFields.length} 个通道`);
    renderShapeChart(curveData);
  } else {
    console.log('✗ 板形数据为空或不存在');
  }

  // 获取并渲染一次项系数DS-OS图表
  const { modelData } = await fetchPriTermData(inMatNo);

  if (modelData && modelData["PriTerm"] && modelData["QuaTerm"]) {
    renderPriTermChart(modelData);
  }
};

// 5机架张力差图表
const renderTensionChart = (data: number[]) => {
  const dom = document.getElementById('app_tension');
  if (!dom) {
    console.error('app_tension DOM元素不存在');
    return;
  }

  if (!tensionChartInstance) {
    tensionChartInstance = echarts.init(dom);
  }
  tensionChartInstance.clear();

  const xData = Array.from({ length: data.length }, (_, i) => i + 1);

  const option: EChartsOption = {
    tooltip: { trigger: 'axis' },
    grid: { left: '10%', right: '8%', top: '10%', bottom: '15%' },
    xAxis: {
      type: 'category',
      data: xData,
      name: '(m)',
      axisLabel: { fontSize: 10 },
    },
    yAxis: {
      type: 'value',
      name: 'kN',
      axisLabel: { fontSize: 10 },
      scale: true,
    },
    series: [{
      type: 'line',
      data: data,
      smooth: true,
      symbol: 'none',
      lineStyle: { color: '#5470C6' },
    }],
  };
  tensionChartInstance.setOption(option);
};

// 速度-长度序列图表
const renderSpeedChart = (data: number[]) => {
  const dom = document.getElementById('app11');
  if (!dom) {
    console.error('app11 DOM元素不存在');
    return;
  }

  if (!speedChartInstance) {
    speedChartInstance = echarts.init(dom);
  }
  speedChartInstance.clear();

  const xData = Array.from({ length: data.length }, (_, i) => i + 1);

  const option: EChartsOption = {
    tooltip: { trigger: 'axis' },
    grid: { left: '10%', right: '8%', top: '10%', bottom: '15%' },
    xAxis: {
      type: 'category',
      data: xData,
      name: '(m)',
      axisLabel: { fontSize: 10 },
    },
    yAxis: {
      type: 'value',
      name: 'm/min',
      axisLabel: { fontSize: 10 },
      scale: true,
    },
    series: [{
      type: 'line',
      data: data.map(v => Math.floor(v * 100) / 100),
      step: 'start',
      symbol: 'none',
      lineStyle: { color: '#91CC75' },
    }],
  };
  speedChartInstance.setOption(option);
};

// 组合图（张力差/轧制力差/倾斜）
const renderCombinedChart = (data: { ten: number[]; force: number[]; tilt: number[] }) => {
  const dom = document.getElementById('app_combined');
  if (!dom) {
    console.error('app_combined DOM元素不存在');
    return;
  }
  if (!combinedChartInstance) {
    combinedChartInstance = echarts.init(dom);
  }
  combinedChartInstance.clear();

  const maxLen = Math.max(data.ten.length, data.force.length, data.tilt.length);
  const xData = Array.from({ length: maxLen }, (_, i) => i + 1);

  const option: EChartsOption = {
    tooltip: { trigger: 'axis' },
    grid: { left: '10%', right: '15%', top: '10%', bottom: '18%' },
    legend: {
      data: ['5机架轧制力差', '5机架张力差', 'S5机架倾斜'],
      bottom: 5,
      textStyle: { fontSize: 10 },
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: xData,
      axisLabel: { fontSize: 10 },
      name: '(m)'
    },
    yAxis: [
      {
        type: 'value',
        name: 'kN', // 左轴：力/张力差
        position: 'left',
        axisLabel: { fontSize: 10 },
        splitLine: { show: false },
        scale: true
      },
      {
        type: 'value',
        name: 'mm', // 右轴：倾斜
        position: 'right',
        axisLabel: { fontSize: 10 },
        splitLine: { show: false },
        scale: true
      },
    ],
    series: [
      {
        name: '5机架轧制力差',
        type: 'line',
        step: 'middle',
        data: data.force,
        yAxisIndex: 0,
        symbol: 'none',
        lineStyle: { color: '#EE6666' }, // 红色线条
        itemStyle: { color: '#EE6666' } // 红色图例和悬浮提示
      },
      {
        name: '5机架张力差',
        type: 'line',
        step: 'start',
        data: data.ten,
        yAxisIndex: 0,
        symbol: 'none',
        lineStyle: { color: '#91CC75' }, // 绿色线条
        itemStyle: { color: '#91CC75' } // 绿色图例和悬浮提示
      },
      {
        name: 'S5机架倾斜',
        type: 'line',
        step: 'end',
        data: data.tilt,
        yAxisIndex: 1,
        symbol: 'none',
        lineStyle: { color: '#5470C6' }, // 蓝色线条
        itemStyle: { color: '#5470C6' } // 蓝色图例和悬浮提示
      }
    ]
  };

  combinedChartInstance.setOption(option);
};

// 5机架轧制力差图表
const renderForceChart = (data: number[]) => {
  const dom = document.getElementById('app5');
  if (!dom) {
    console.error('app5 DOM元素不存在');
    return;
  }

  if (!forceChartInstance) {
    forceChartInstance = echarts.init(dom);
  }
  forceChartInstance.clear();

  const xData = Array.from({ length: data.length }, (_, i) => i + 1);

  const option: EChartsOption = {
    tooltip: { trigger: 'axis' },
    grid: { left: '10%', right: '8%', top: '10%', bottom: '15%' },
    xAxis: {
      type: 'category',
      data: xData,
      name: '(m)',
      axisLabel: { fontSize: 10 },
    },
    yAxis: {
      type: 'value',
      axisLabel: { fontSize: 10 },
      scale: true,
    },
    series: [{
      type: 'line',
      data: data,
      step: 'middle',
      symbol: 'none',
      lineStyle: { color: '#67c23a' },
      itemStyle: { color: '#67c23a' },
    }],
  };
  forceChartInstance.setOption(option);
};

// S5机架倾斜图表
const renderTiltChart = (data: number[]) => {
  const dom = document.getElementById('app_tilt');
  if (!dom) {
    console.error('app_tilt DOM元素不存在');
    return;
  }

  if (!tiltChartInstance) {
    tiltChartInstance = echarts.init(dom);
  }
  tiltChartInstance.clear();

  const xData = Array.from({ length: data.length }, (_, i) => i + 1);

  const option: EChartsOption = {
    tooltip: { trigger: 'axis' },
    grid: { left: '10%', right: '8%', top: '10%', bottom: '15%' },
    xAxis: {
      type: 'category',
      data: xData,
      name: '(m)',
      axisLabel: { fontSize: 10 },
    },
    yAxis: {
      type: 'value',
      name: 'mm',
      axisLabel: { fontSize: 10 },
      scale: true,
    },
    series: [{
      type: 'line',
      data: data,
      smooth: true,
      symbol: 'none',
      lineStyle: { color: '#5470C6' },
    }],
  };
  tiltChartInstance.setOption(option);
};

// 板形仪通道号图表 - 与 PlanRollDeviationPrediction.vue 完全一致的渲染方式
const renderShapeChart = (dataObj: any) => {
  const dom = document.getElementById('app7');
  if (!dom) {
    console.error('app7 DOM元素不存在');
    return;
  }

  if (!shapeChartInstance) {
    shapeChartInstance = echarts.init(dom);
  }
  shapeChartInstance.clear();

  let res: any[] = [];
  let max = 0;
  let need_x11: number[] = [];

  // 只查找 tcm_shape_channe_ 前缀的字段，与 PlanRollDeviationPrediction.vue 一致
  Object.entries(dataObj).forEach(([key, value]) => {
    const matchReq = /^tcm_shape_channe_(\d+)$/.exec(key);
    if (!matchReq) return;

    // 过滤全为0的数据
    if (Array.isArray(value) && (value as any[]).every((i: any) => i === 0)) return;

    const index = Number(matchReq[1]);
    max = Math.max(max, index);

    if (Array.isArray(value)) {
      (value as any[]).forEach((v: any, i: any) => {
        res.push([i - 1, index, v]);  // X轴值减1（原来的1现在显示为0）
        if (need_x11.length < (value as any[]).length) {
          need_x11.push(i - 1);  // X轴值减1
        }
      });
    }
  });

  if (res.length === 0) {
    console.warn('板形数据处理后为空');
    console.log('可用的 shape 字段:', Object.keys(dataObj).filter(k => k.includes('shape')));
    return;
  }

  console.log(`✓ 成功处理板形数据，共 ${res.length} 个点，最大通道号: ${max}`);

  const days = Array.from({ length: 64 }, (_, i) => `c_${i}`);

  const option: EChartsOption = {
    title: {
      text: '板形仪通道号(长度序列)',
      textStyle: {
        color: '#222',
        fontStyle: 'normal',
        fontWeight: 'bold',
        fontFamily: 'sans-serif',
        fontSize: 14
      }
    },
    tooltip: {
      position: 'top',
      textStyle: {
        color: '#222',
        fontSize: 12
      }
    },
    grid: { left: '8%', right: '15%', top: '10%', bottom: '10%', containLabel: true },
    xAxis: {
      type: 'category',
      data: need_x11,
      name: '(m)',
      nameTextStyle: {
        fontSize: 12,
        color: '#222'
      },
      axisLabel: {
        fontSize: 10,
        color: '#222'
      },
      axisLine: {
        lineStyle: {
          color: '#888',
          width: 1
        }
      },
      splitLine: {
        show: true,
        lineStyle: {
          type: 'dotted',
          color: '#ccc'
        }
      }
    },
    yAxis: {
      type: 'category',
      data: days,
      nameTextStyle: {
        fontSize: 12,
        color: '#222'
      },
      axisLabel: {
        fontSize: 10,
        color: '#222'
      },
      axisLine: {
        lineStyle: {
          color: '#888',
          width: 1
        }
      },
      splitLine: {
        show: true,
        lineStyle: {
          type: 'dotted',
          color: '#ccc'
        }
      }
    },
    visualMap: {
      min: -25,
      max: 25,
      calculable: true,
      orient: 'vertical',
      left: 'right',
      top: 'center',
      realtime: false,
      textStyle: {
        fontSize: 10,
        color: '#222'
      },
      inRange: {
        color: [
          'RGB(0,10,255)',
          'RGB(0,150,255)',
          'RGB(0,199,255)',
          '#11fff9',
          'RGB(0,255,0)',
          '#FFF500',
          'RGB(255,230,0)',
          'RGB(249, 102, 72)',
          'RGB(255,0,0)',
        ],
      },
    },
    series: [{
      type: 'heatmap',
      data: res.sort((a: any, b: any) => a[0] - b[0]),
      pointSize: 10,
    }],
  };
  shapeChartInstance.setOption(option, true);
};

// 一次项系数DS-OS图表 - 与 LayOutJudge.vue 完全一致的渲染方式
const renderPriTermChart = (modelData: any) => {
  const dom = document.getElementById('app_priterm');
  if (!dom) {
    console.error('app_priterm DOM元素不存在');
    return;
  }

  if (!modelData["PriTerm"]) {
    console.warn('一次项系数数据不存在');
    return;
  }

  if (!priTermChartInstance) {
    priTermChartInstance = echarts.init(dom);
  }
  priTermChartInstance.clear();

  const arrlength: any[] = [];
  const need_y1: any[] = [];

  // X轴显示：原始索引减1（原来的1现在显示为0）
  for (let i = 0; i < modelData["PriTerm"].length; i++) {
    arrlength.push(i - 1);  // X轴值减1
    need_y1.push(Math.floor(modelData["PriTerm"][i] * 100) / 100);
  }

  const option: EChartsOption = {
    color: 'yellow',
    tooltip: {
      trigger: 'axis',
      backgroundColor: 'rgba(32, 33, 36,.7)',
      borderColor: 'rgba(32, 33, 36,0.20)',
      borderWidth: 1,
      textStyle: {
        color: '#fff',
        fontSize: 12
      },
      axisPointer: {
        type: 'cross',
        label: {
          backgroundColor: '#6a7985'
        }
      }
    },
    grid: {
      left: '8%',
      right: '6%',
      bottom: '15%',
      top: '10%',
      containLabel: true
    },
    dataZoom: [
      {
        type: 'slider',
        show: true,
        xAxisIndex: [0],
        start: 0,
        end: 100
      },
      {
        type: 'inside',
        xAxisIndex: [0],
        start: 0,
        end: 100
      }
    ],
    xAxis: {
      type: 'category',
      boundaryGap: false,
      axisLine: {
        lineStyle: {
          color: '#888'
        }
      },
      splitLine: {
        show: true,
        lineStyle: {
          type: 'dotted',
          color: '#ddd'
        }
      },
      nameTextStyle: {
        color: '#333',
        fontSize: 12
      },
      name: '(m)',
      data: arrlength,
      axisLabel: {
        color: '#333',
        fontSize: 10
      }
    },
    yAxis: {
      type: 'value',
      splitLine: {
        show: true,
        lineStyle: {
          type: 'dotted',
          color: '#ddd'
        }
      },
      axisLine: {
        lineStyle: {
          color: '#888'
        }
      },
      nameTextStyle: {
        fontSize: 12,
        color: '#333'
      },
      axisLabel: {
        formatter: '{value}',
        color: '#333',
        fontSize: 10
      },
      scale: true
    },
    series: [
      {
        name: '一次项系数（蓝色）值越大，DS侧非对称浪形越大',
        type: 'line',
        data: need_y1,
        smooth: true,
        symbol: 'none',
        lineStyle: {
          color: '#5470C6'
        }
      }
    ]
  };

  priTermChartInstance.setOption(option);
};

// --- Chart Cleanup & Resize ---
const disposeCharts = () => {
  cpcChartInstances.forEach((chart) => chart?.dispose());
  convexityWedgeChartInstance?.dispose();
  processTraceChartInstance?.dispose();
  cpcChartInstances = [];
  convexityWedgeChartInstance = null;
  processTraceChartInstance = null;
  if (cpcBigChartInstance) {
    cpcBigChartInstance.dispose();
    cpcBigChartInstance = null;
  }

  // 销毁右侧图表
  tensionChartInstance?.dispose();
  speedChartInstance?.dispose();
  forceChartInstance?.dispose();
  tiltChartInstance?.dispose();
  shapeChartInstance?.dispose();
  priTermChartInstance?.dispose();
  combinedChartInstance?.dispose();
  tensionChartInstance = null;
  speedChartInstance = null;
  forceChartInstance = null;
  tiltChartInstance = null;
  shapeChartInstance = null;
  priTermChartInstance = null;
  combinedChartInstance = null;

  // 销毁工艺参数曲线图表
  processTempChartInstance?.dispose();
  processTensionChartInstance?.dispose();
  processSpeedChartInstance?.dispose();
  processLooperChartInstance?.dispose();
  processTempChartInstance = null;
  processTensionChartInstance = null;
  processSpeedChartInstance = null;
  processLooperChartInstance = null;
};

const handleDialogClose = () => {
  disposeCharts();
  // 清空缓存数据
  cachedPriTermData = null;
};

const handleResize = () => {
  cpcChartInstances.forEach((chart) => chart?.resize());
  convexityWedgeChartInstance?.resize();
  processTraceChartInstance?.resize();
  cpcBigChartInstance?.resize();

  // 调整右侧图表大小
  tensionChartInstance?.resize();
  speedChartInstance?.resize();
  forceChartInstance?.resize();
  tiltChartInstance?.resize();
  shapeChartInstance?.resize();
  priTermChartInstance?.resize();
  combinedChartInstance?.resize();

  // 调整工艺参数曲线图表大小
  processTempChartInstance?.resize();
  processTensionChartInstance?.resize();
  processSpeedChartInstance?.resize();
  processLooperChartInstance?.resize();
};

const handleDialogOpened = () => {
  setTimeout(async () => {
    initDetailCharts();
    await initRightCharts();
    // 渲染工艺参数曲线
    renderProcessCurveCharts();
    // 渲染选中的图表
    renderSelectedCharts();
  }, 100);
};

// 渲染选中的图表
const renderSelectedCharts = async () => {
  for (const chartId of selectedCharts.value) {
    switch (chartId) {
      case 'app7':
        // 板形仪通道号图表已经在 initRightCharts 中渲染
        break;
      case 'app11':
        // 5机架速度图表已经在 initRightCharts 中渲染
        break;
      case 'app_combined':
        // 生产过程追溯图表已经在 initRightCharts 中渲染
        break;
      case 'process_temp_chart':
        renderProcessTempChart();
        break;
      case 'process_tension_chart':
        renderProcessTensionChart();
        break;
      case 'process_speed_chart':
        renderProcessSpeedChart();
        break;
      case 'process_looper_chart':
        renderProcessLooperChart();
        break;
      case 'app_priterm':
        // 一次项系数图表：如果有缓存数据就使用缓存，否则重新获取
        if (cachedPriTermData && cachedPriTermData.PriTerm) {
          console.log('✅ 使用缓存的一次项系数数据');
          renderPriTermChart(cachedPriTermData);
        } else if (detailData.entid) {
          console.log('✅ 重新获取一次项系数数据');
          const { modelData } = await fetchPriTermData(detailData.entid);
          if (modelData && modelData.PriTerm) {
            renderPriTermChart(modelData);
          }
        }
        break;
    }
  }
};

// 监听选中图表变化
watch(selectedCharts, async (newCharts, oldCharts) => {
  // 销毁不再选中的图表
  if (oldCharts) {
    oldCharts.forEach(chartId => {
      if (!newCharts.includes(chartId)) {
        disposeChartById(chartId);
      }
    });
  }
  
  // 渲染新选中的图表
  setTimeout(async () => {
    await renderSelectedCharts();
  }, 100);
}, { deep: true });

// 根据ID销毁特定图表
const disposeChartById = (chartId: string) => {
  switch (chartId) {
    case 'app7':
      shapeChartInstance?.dispose();
      shapeChartInstance = null;
      break;
    case 'app11':
      speedChartInstance?.dispose();
      speedChartInstance = null;
      break;
    case 'app_combined':
      combinedChartInstance?.dispose();
      combinedChartInstance = null;
      break;
    case 'process_temp_chart':
      processTempChartInstance?.dispose();
      processTempChartInstance = null;
      break;
    case 'process_tension_chart':
      processTensionChartInstance?.dispose();
      processTensionChartInstance = null;
      break;
    case 'process_speed_chart':
      processSpeedChartInstance?.dispose();
      processSpeedChartInstance = null;
      break;
    case 'process_looper_chart':
      processLooperChartInstance?.dispose();
      processLooperChartInstance = null;
      break;
    case 'app_priterm':
      priTermChartInstance?.dispose();
      priTermChartInstance = null;
      break;
  }
};

onMounted(() => {
  window.addEventListener('resize', handleResize);
  handleSearch(); // Load initial data
});

onUnmounted(() => {
  window.removeEventListener('resize', handleResize);
  disposeCharts(); // Ensure cleanup on component unmount
});

// 字段label映射
function getFieldLabel(key: string): string {
  if (/^cpc(\d+)Avg$/.test(key)) {
    const idx = Number(key.match(/^cpc(\d+)Avg$/)![1]);
    if (idx < 90) return `CPC${idx}`;
    return `CPC9-${idx - 90}`;
  }
  if (/^cpc(\d+)StripMax$/.test(key)) {
    const idx = Number(key.match(/^cpc(\d+)StripMax$/)![1]);
    if (idx < 90) return `CPC${idx}`;
    return `CPC9-${idx - 90}`;
  }
  if (/^cpc(\d+)StripAvg$/.test(key)) {
    const idx = Number(key.match(/^cpc(\d+)StripAvg$/)![1]);
    if (idx < 90) return `CPC${idx}`;
    return `CPC9-${idx - 90}`;
  }
  const map: Record<string, string> = {
    extid: '出口卷号',
    steelGrade: '钢种',
    width: '宽度',
    thick: '厚度',
    gradeCode: '钢种分档',
    widthCode: '宽度分档',
    thickCode: '厚度分档',
    paopianFlag: '纠偏满载',
    paopianFlagTrue: '是否跑偏',
    prodEndTime: '生产结束时间',
    shiftNo: '班次',
    entid: '入口卷号',
    entryThick: '入口厚度',
    entryWidth: '入口宽度',
    entryLength: '入口长度',
    hotCoilId: '热卷号',
    paopianRate: '预测跑偏概率',
    c40Passrate: '凸度命中率',
    w40Passrate: '楔形命中率',
    length: '长度',
    // ...可继续补充
  };
  return map[key] || key;
}
// 判断时间字段
function isTimeField(key: string): boolean {
  return key.toLowerCase().includes('time');
}
// 时间格式化
// function formatDate(val: any): string {
//   if (!val) return '-'; //
//   const date = new Date(Number(val));
//   if (isNaN(date.getTime())) return '-';
//   const y = date.getFullYear();
//   const m = String(date.getMonth() + 1).padStart(2, '0');
//   const d = String(date.getDate()).padStart(2, '0');
//   const h = String(date.getHours()).padStart(2, '0');
//   const min = String(date.getMinutes()).padStart(2, '0');
//   const s = String(date.getSeconds()).padStart(2, '0');
//   return `${y}-${m}-${d} ${h}:${min}:${s}`;
// }
function formatDate(val: string | number): string {
  const s = String(val).trim();
  // 期望长度14位：yyyyMMddHHmmss
  if (s.length !== 14 || !/^\d{14}$/.test(s)) return '';

  const y = s.slice(0, 4);
  const M = s.slice(4, 6);
  const d = s.slice(6, 8);
  const h = s.slice(8, 10);
  const m = s.slice(10, 12);
  const sec = s.slice(12, 14);

  return `${y}-${M}-${d} ${h}:${m}:${sec}`;
}
// 自动提取主表基础字段和CPC相关字段
const baseTableFields = computed(() => {
  if (!tableData.length) return [];
  const allKeys = Object.keys(tableData[0]);
  // 基础字段优先（排除已在表头显式渲染的字段，避免重复列）
  const explicitCols = new Set(['extid', 'steelGrade', 'width', 'thick', 'entid', 'prodEndTime']);
  const base = [
    'extid',
    'steelGrade',
    'width',
    'thick',
    'gradeCode',
    'widthCode',
    'thickCode',
    'paopianFlag',
    'paopianFlagTrue',
    'prodEndTime',
    'shiftNo',
    'entid',
    'entryThick',
    'entryWidth',
    'entryLength',
    'hotCoilId',
    'paopianRate',
    'c40Passrate',
    'w40Passrate',
    'length',
  ];
  return base.filter((k) => allKeys.includes(k) && !explicitCols.has(k));
});
// 详情弹窗基础字段和CPC相关字段
const baseDetailFields = computed(() => {
  const allKeys = Object.keys(detailData);
  const base = [
    'extid',
    'entid',
    'steelGrade',
    'width',
    'thick',
    'gradeCode',
    'widthCode',
    'thickCode',
    'paopianFlag',
    'paopianFlagTrue',
    'prodEndTime',
    'shiftNo',
    'entryThick',
    'entryWidth',
    'entryLength',
    'hotCoilId',
    'paopianRate',
    'c40Passrate',
    'w40Passrate',
    'length',
  ];
  return base.filter((k) => allKeys.includes(k));
});
// 自动提取主表CPC分组字段
const cpcAvgFields = computed(() => {
  if (!tableData.length) return [];
  return Object.keys(tableData[0]).filter((k) => /^cpc(\d+)Avg$/.test(k));
});
const cpcStripAvgFields = computed(() => {
  if (!tableData.length) return [];
  return Object.keys(tableData[0]).filter((k) => /^cpc(\d+)StripAvg$/.test(k));
});
const cpcStripMaxFields = computed(() => {
  if (!tableData.length) return [];
  return Object.keys(tableData[0]).filter((k) => /^cpc(\d+)StripMax$/.test(k));
});
</script>

<style scoped>
/* ... (之前的样式保持不变) ... */
.aprd-container {
  padding: 15px;
  background-image: linear-gradient(to top, white, #2c69e8) !important;
  height: 100%;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
}

.aprd-search-container {
  margin-bottom: 15px;
  padding: 10px 15px;
  background-color: rgba(245, 247, 250, 0.8);
  border-radius: 4px;
  flex-shrink: 0;
}

.aprd-search-form .el-form-item {
  margin-bottom: 8px;
  margin-right: 10px;
}

:deep(.aprd-search-form .el-input--small .el-input__wrapper),
:deep(.aprd-search-form .el-select--small .el-select__wrapper),
:deep(.aprd-search-form .el-date-editor--small.el-input__wrapper) {
  height: 28px;
  line-height: 28px;
}

:deep(.aprd-search-form .el-input--small .el-input__inner),
:deep(.aprd-search-form .el-select--small .el-select__input-wrapper input),
:deep(.aprd-search-form .el-date-editor--small .el-range-input),
:deep(.aprd-search-form .el-date-editor--small .el-range-separator) {
  height: 26px !important;
  line-height: 26px !important;
  font-size: 12px !important;
}

:deep(.aprd-search-form .el-select--small) {
  width: 150px;
}

:deep(.aprd-search-form .el-form-item__label) {
  font-size: 12px;
  line-height: 28px;
  color: #606266;
  padding-right: 8px;
}

.aprd-table-container {
  flex-grow: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: 0;
  /* Added border and background for context */
  border: 1px solid #dcdfe6;
  background-color: #fff;
  border-radius: 4px;
}

:deep(.el-table) {
  font-size: 12px;
}

:deep(.el-table th.el-table__cell) {
  padding: 6px 0;
  background-color: #f5f7fa !important;
  /* Lighter header */
  color: #606266 !important;
  font-weight: 500;
}

:deep(.el-table td.el-table__cell) {
  padding: 4px 0;
}

:deep(.el-table .el-table__cell) {
  text-align: center;
}

:deep(.el-table__body tr td.el-table-fixed-column--left),
:deep(.el-table__body tr td.el-table-fixed-column--right) {
  /* Ensure fixed columns have background consistent with row */
  background-color: inherit !important;
}

:deep(.el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell) {
  background-color: #ecf5ff !important;
}

:deep(.el-table__body tr.current-row > td.el-table__cell) {
  background-color: #d9ecff !important;
}

.aprd-pagination {
  margin-top: 15px;
  padding: 5px 10px;
  background-color: #fff;
  /* Match table container background */
  border-top: 1px solid #dcdfe6;
  border-radius: 0 0 4px 4px;
  display: flex;
  justify-content: flex-end;
  flex-shrink: 0;
}

/* --- Detail Dialog Styles --- */
:deep(.aprd-detail-dialog .el-dialog__header) {
  background-color: #f5f7fa;
  /* Light header background */
  padding: 10px 20px;
  margin-right: 0;
  border-bottom: 1px solid #e4e7ed;
}

:deep(.aprd-detail-dialog .el-dialog__title) {
  color: #303133;
  /* Darker title color */
  font-size: 16px;
  font-weight: 600;
}

:deep(.aprd-detail-dialog .el-dialog__headerbtn .el-dialog__close) {
  color: #909399;
}

:deep(.aprd-detail-dialog .el-dialog__headerbtn .el-dialog__close:hover) {
  color: #409eff;
}

:deep(.aprd-detail-dialog .el-dialog__body) {
  padding: 0;
  /* Remove default body padding */
}

.aprd-detail-container {
  padding: 15px;
  max-height: calc(90vh - 50px - 60px);
  /* Viewport height - top offset - header - footer */
  overflow-y: auto;
  background-color: #fff;
  /* Ensure white background inside */
}

.aprd-detail-info {
  margin-bottom: 15px;
}

:deep(.aprd-detail-info .el-descriptions__label) {
  background-color: #f5f7fa;
  font-weight: normal;
  color: #606266;
}

:deep(.aprd-detail-info .el-descriptions__content) {
  color: #303133;
}

.aprd-detail-charts-area {
  display: flex;
  gap: 15px;
  min-height: 600px;
}

.aprd-left-charts {
  flex: 1;
  width: 50%;
  overflow-y: auto;
}

.aprd-right-charts {
  flex: 1;
  width: 50%;
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow-y: auto;
}

/* 图表选择器样式 */
.aprd-chart-selector {
  background: #f8f9fa;
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  padding: 12px;
  margin-bottom: 10px;
  flex-shrink: 0;
}

.aprd-selector-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.aprd-selector-title {
  font-size: 14px;
  font-weight: 600;
  color: #303133;
}

/* 动态图表容器 */
.aprd-dynamic-charts {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
  overflow-y: auto;
}

.aprd-cpc-charts-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  max-height: 100%;
  width: 100%;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  background: #fff;
}

.aprd-cpc-chart-item {
  width: 100%;
  min-width: 220px;
  background: transparent;
  border-left: none;
  border-right: none;
  border-top: none;
  border-bottom: 1px solid #e4e7ed;
  border-radius: 0;
  margin-bottom: 0;
  display: flex;
  flex-direction: row;
  /* 横向排列 */
  align-items: center;
}

.aprd-cpc-chart-title {
  font-size: 14px;
  color: #333;
  min-width: 40px;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  background: none;
  border-bottom: none;
  padding: 0;
}

.aprd-cpc-chart {
  height: 120px;
  min-width: 180px;
  flex: 1;
}

.aprd-right-charts .aprd-chart-item {
  flex-shrink: 0;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  background: #fff;
  overflow: hidden;
}

.aprd-right-charts .aprd-chart-item-large {
  min-height: 380px;
}

.aprd-right-charts .aprd-chart-title {
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 600;
  color: #303133;
  background-color: #f5f7fa;
  border-bottom: 1px solid #e4e7ed;
}

.aprd-right-charts .aprd-chart {
  height: 200px;
  width: 100%;
}

.aprd-right-charts .aprd-chart-large {
  height: 340px;
}

/* Scrollbar styling for detail container */
.aprd-detail-container::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.aprd-detail-container::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.aprd-detail-container::-webkit-scrollbar-thumb {
  background-color: #c0c4cc;
  border-radius: 3px;
}

.aprd-detail-container::-webkit-scrollbar-thumb:hover {
  background-color: #a8abb2;
}

/* Footer alignment */
.dialog-footer {
  display: flex;
  justify-content: flex-end;
}
</style>
